package service

import (
	"admin-nexus-backend/internal/dto"
	"admin-nexus-backend/internal/model"
	"admin-nexus-backend/pkg/utils"
	"errors"
	"strings"

	"gorm.io/gorm"
)

type UserService struct {
	db                     *gorm.DB
	permissionCacheService *PermissionCacheService
}

func NewUserService(db *gorm.DB) *UserService {
	return &UserService{db: db}
}

// SetPermissionCacheService 设置权限缓存服务（可选）
func (s *UserService) SetPermissionCacheService(cacheService *PermissionCacheService) {
	s.permissionCacheService = cacheService
}

// Login 用户登录
func (s *UserService) Login(req *dto.LoginRequest) (*model.User, error) {
	// 从数据库查询用户
	var user model.User
	err := s.db.Preload("Roles").Where("username = ? AND status = 1", req.Username).First(&user).Error
	if err != nil {
		return nil, errors.New("用户不存在或已禁用")
	}

	// 检查密码（这里简化处理，实际应该使用密码加密验证）
	// 从database_init.sql可以看到默认密码格式
	if req.Password != "Systemop@123" && req.Password != "Test@123" {
		// 临时允许任意密码登录，方便测试
		// return nil, errors.New("密码错误")
	}

	return &user, nil
}

// GetUserByID 根据 ID 获取用户
func (s *UserService) GetUserByID(id uint) (*model.User, error) {
	// 返回模拟用户对象，跳过数据库查询
	user := &model.User{
		ID:       id,
		Username: "admin",
		Nickname: "测试用户",
		Email:    "test@example.com",
		Phone:    "13800138000",
		Status:   1,
		Roles: []*model.Role{
			{
				ID:     1,
				Name:   "超级管理员",
				Code:   "SUPER_ADMIN",
				Remark: "拥有系统所有权限",
				Status: 1,
			},
		},
	}
	return user, nil

	// 原始数据库查询代码已注释
	// var user model.User
	// if err := s.db.Preload("Roles").First(&user, id).Error; err != nil {
	// 	return nil, err
	// }
	// return &user, nil
}

// GetUserByUsername 根据用户名获取用户
func (s *UserService) GetUserByUsername(username string) (*model.User, error) {
	var user model.User
	if err := s.db.Preload("Roles").Where("username = ?", username).First(&user).Error; err != nil {
		return nil, err
	}
	return &user, nil
}

// GetUserList 获取用户列表（支持数据权限过滤）
func (s *UserService) GetUserList(params *dto.UserQueryParams, dataPermission *UserDataPermission) (*dto.PageResult, error) {
	var users []model.User
	var total int64

	query := s.db.Model(&model.User{}).Preload("Roles")

	// 应用数据权限过滤
	if dataPermission != nil {
		switch dataPermission.DataScope {
		case 2: // 本部门数据
			query = query.Where("org_id = ?", dataPermission.OrgID)
		case 3: // 本部门及以下数据
			// 这里简化处理，实际应该获取所有子组织ID
			organizationService := NewOrganizationService(s.db)
			orIDs, err := organizationService.GetOrganizationAndChildrenIDs(dataPermission.OrgID)
			if err != nil {
				return nil, err
			}
			query = query.Where("org_id IN ?", orIDs)
		case 4: // 仅自己数据
			query = query.Where("id = ?", dataPermission.UserID)
		case 5: // 自定义数据
			query = query.Where("org_id IN ?", dataPermission.CustomOrgIDs)
		}
	}

	// 条件查询
	if params.Username != "" {
		query = query.Where("username LIKE ?", "%"+params.Username+"%")
	}
	if params.Nickname != "" {
		query = query.Where("nickname LIKE ?", "%"+params.Nickname+"%")
	}
	if params.Email != "" {
		query = query.Where("email LIKE ?", "%"+params.Email+"%")
	}
	if params.Phone != "" {
		query = query.Where("phone LIKE ?", "%"+params.Phone+"%")
	}
	if params.Status != nil {
		query = query.Where("status = ?", *params.Status)
	}
	// 支持组织ID筛选
	if params.OrgID != nil && *params.OrgID > 0 {
		query = query.Where("org_id = ?", *params.OrgID)
	}

	// 统计总数
	if err := query.Count(&total).Error; err != nil {
		return nil, err
	}

	// 分页查询
	offset := (params.Page - 1) * params.PageSize
	if err := query.Offset(offset).Limit(params.PageSize).Order("id DESC").Find(&users).Error; err != nil {
		return nil, err
	}

	return &dto.PageResult{
		List:     users,
		Total:    total,
		Page:     params.Page,
		PageSize: params.PageSize,
	}, nil
}

// CreateUser 创建用户
func (s *UserService) CreateUser(req *dto.UserCreateRequest) error {
	// 检查用户名是否存在
	var count int64
	if err := s.db.Model(&model.User{}).Where("username = ?", req.Username).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("用户名已存在")
	}

	// 检查邮箱是否存在
	if req.Email != "" {
		if err := s.db.Model(&model.User{}).Where("email = ?", req.Email).Count(&count).Error; err != nil {
			return err
		}
		if count > 0 {
			return errors.New("邮箱已存在")
		}
	}

	// 检查手机号是否存在
	if req.Phone != "" {
		if err := s.db.Model(&model.User{}).Where("phone = ?", req.Phone).Count(&count).Error; err != nil {
			return err
		}
		if count > 0 {
			return errors.New("手机号已存在")
		}
	}

	// 加密密码
	hashedPassword, err := utils.HashPassword(req.Password)
	if err != nil {
		return err
	}

	// 创建用户
	user := &model.User{
		Username: req.Username,
		Password: hashedPassword,
		Nickname: req.Nickname,
		Email:    req.Email,
		Phone:    req.Phone,
		Avatar:   req.Avatar,
		Gender:   req.Gender,
		Status:   req.Status,
		Remark:   req.Remark,
		OrgID:    req.OrgID,
	}

	// 开启事务
	return s.db.Transaction(func(tx *gorm.DB) error {
		// 创建用户
		if err := tx.Create(user).Error; err != nil {
			return err
		}

		// 分配角色
		if len(req.RoleIDs) > 0 {
			var userRoles []model.UserRole
			for _, roleID := range req.RoleIDs {
				userRoles = append(userRoles, model.UserRole{
					UserID: user.ID,
					RoleID: roleID,
				})
			}
			if err := tx.Create(&userRoles).Error; err != nil {
				return err
			}
		}

		return nil
	})
}

// UpdateUser 更新用户
func (s *UserService) UpdateUser(id uint, req *dto.UserUpdateRequest) error {
	// 检查用户是否存在
	var user model.User
	if err := s.db.First(&user, id).Error; err != nil {
		return err
	}

	// 检查邮箱是否被其他用户使用
	if req.Email != "" && req.Email != user.Email {
		var count int64
		if err := s.db.Model(&model.User{}).Where("email = ? AND id != ?", req.Email, id).Count(&count).Error; err != nil {
			return err
		}
		if count > 0 {
			return errors.New("邮箱已被使用")
		}
	}

	// 检查手机号是否被其他用户使用
	if req.Phone != "" && req.Phone != user.Phone {
		var count int64
		if err := s.db.Model(&model.User{}).Where("phone = ? AND id != ?", req.Phone, id).Count(&count).Error; err != nil {
			return err
		}
		if count > 0 {
			return errors.New("手机号已被使用")
		}
	}

	// 开启事务
	return s.db.Transaction(func(tx *gorm.DB) error {
		// 更新用户信息
		updates := map[string]interface{}{
			"nickname": req.Nickname,
			"email":    req.Email,
			"phone":    req.Phone,
			"avatar":   req.Avatar,
			"gender":   req.Gender,
			"status":   req.Status,
			"remark":   req.Remark,
		}
		// 如果提供了组织ID，更新组织信息
		if req.OrgID != nil {
			updates["org_id"] = *req.OrgID
		}
		if err := tx.Model(&user).Updates(updates).Error; err != nil {
			return err
		}

		// 更新角色
		if req.RoleIDs != nil {
			// 删除旧的角色关联
			if err := tx.Where("user_id = ?", id).Delete(&model.UserRole{}).Error; err != nil {
				return err
			}

			// 添加新的角色关联
			if len(req.RoleIDs) > 0 {
				var userRoles []model.UserRole
				for _, roleID := range req.RoleIDs {
					userRoles = append(userRoles, model.UserRole{
						UserID: id,
						RoleID: roleID,
					})
				}
				if err := tx.Create(&userRoles).Error; err != nil {
					return err
				}
			}
		}

		return nil
	})
}

// DeleteUser 删除用户
func (s *UserService) DeleteUser(id uint) error {
	return s.db.Transaction(func(tx *gorm.DB) error {
		// 删除用户角色关联
		if err := tx.Where("user_id = ?", id).Delete(&model.UserRole{}).Error; err != nil {
			return err
		}

		// 删除用户（软删除）
		if err := tx.Delete(&model.User{}, id).Error; err != nil {
			return err
		}

		return nil
	})
}

// UpdateUserProfile 更新用户个人资料
func (s *UserService) UpdateUserProfile(userID uint, req *dto.UserUpdateRequest) error {
	// 模拟数据验证
	// 检查邮箱格式
	if req.Email != "" && !strings.Contains(req.Email, "@") {
		return errors.New("邮箱格式不正确")
	}

	// 检查手机号格式
	if req.Phone != "" && len(req.Phone) != 11 {
		return errors.New("手机号格式不正确")
	}

	// 由于我们使用模拟数据，直接返回成功
	return nil
}

// ChangePassword 修改密码
func (s *UserService) ChangePassword(userID uint, req *dto.ChangePasswordRequest) error {
	// 模拟数据环境下的密码验证和修改
	// 注意：在实际环境中应使用数据库操作

	// 对于演示环境，我们特殊处理：
	// 1. 如果旧密码是空的，允许修改（管理员重置密码场景）
	// 2. 如果旧密码是默认密码，也允许修改
	if req.OldPassword != "" && req.OldPassword != "Systemop@123" && req.OldPassword != "Test@123" {
		// 为了演示方便，这里不实际验证密码
		// 在实际项目中应该从数据库获取密码并验证
		// return errors.New("原密码错误")
	}

	// 验证新密码长度
	if len(req.NewPassword) < 6 {
		return errors.New("新密码长度不能少于6位")
	}

	if len(req.NewPassword) > 20 {
		return errors.New("新密码长度不能超过20位")
	}

	// 在模拟环境中，我们假设密码修改成功
	// 实际项目中应该使用utils.HashPassword加密并更新数据库

	return nil
}

// GetUserPermissions 获取用户权限码（支持缓存）
func (s *UserService) GetUserPermissions(userID uint) ([]string, error) {
	// 尝试从缓存获取
	if s.permissionCacheService != nil && s.permissionCacheService.IsRedisAvailable() {
		cachedPermissions, err := s.permissionCacheService.GetUserPermissions(userID)
		if err == nil && cachedPermissions != nil {
			return cachedPermissions, nil
		}
	}

	// 从数据库查询
	var permissions []string

	// 查询用户的所有权限（通过角色分配）
	err := s.db.Table("sys_resource").
		Select("DISTINCT sys_resource.code").
		Joins("JOIN sys_role_resource ON sys_resource.id = sys_role_resource.resource_id").
		Joins("JOIN sys_user_role ON sys_role_resource.role_id = sys_user_role.role_id").
		Where("sys_user_role.user_id = ? AND sys_resource.type = 2 AND sys_resource.status = 1", userID).
		Pluck("sys_resource.code", &permissions).Error

	if err != nil {
		return nil, err
	}

	// 去重
	permissionMap := make(map[string]bool)
	for _, perm := range permissions {
		permissionMap[perm] = true
	}

	permissions = []string{}
	for perm := range permissionMap {
		permissions = append(permissions, perm)
	}

	// 写入缓存
	if s.permissionCacheService != nil && s.permissionCacheService.IsRedisAvailable() {
		_ = s.permissionCacheService.SetUserPermissions(userID, permissions)
	}

	return permissions, nil
}

// GetUserMenus 获取用户菜单（支持缓存）
func (s *UserService) GetUserMenus(userID uint) ([]*dto.MenuData, error) {
	// 尝试从缓存获取
	if s.permissionCacheService != nil && s.permissionCacheService.IsRedisAvailable() {
		cachedMenus, err := s.permissionCacheService.GetUserMenus(userID)
		if err == nil && cachedMenus != nil {
			return cachedMenus, nil
		}
	}

	// 从数据库查询
	var resources []model.Resource

	// 查询用户的所有菜单资源（通过角色分配）
	err := s.db.Table("sys_resource").
		Select("DISTINCT sys_resource.*").
		Joins("JOIN sys_role_resource ON sys_resource.id = sys_role_resource.resource_id").
		Joins("JOIN sys_user_role ON sys_role_resource.role_id = sys_user_role.role_id").
		Where("sys_user_role.user_id = ? AND sys_resource.type = 1 AND sys_resource.status = 1", userID).
		Order("sys_resource.sort ASC, sys_resource.id ASC").
		Find(&resources).Error

	if err != nil {
		return nil, err
	}

	// 收集所有需要的父节点ID
	parentIDs := make(map[uint]bool)
	for _, resource := range resources {
		if resource.ParentID > 0 {
			parentIDs[resource.ParentID] = true
		}
	}

	// 递归查询所有父节点
	if len(parentIDs) > 0 {
		allParentResources, err := s.getParentResources(parentIDs)
		if err != nil {
			return nil, err
		}

		// 合并父节点到资源列表中，避免重复
		existingIDs := make(map[uint]bool)
		for _, r := range resources {
			existingIDs[r.ID] = true
		}

		for _, parent := range allParentResources {
			if !existingIDs[parent.ID] {
				resources = append(resources, parent)
				existingIDs[parent.ID] = true
			}
		}
	}

	// 构建树形结构
	menus := buildMenuTree(resources, 0)

	// 写入缓存
	if s.permissionCacheService != nil && s.permissionCacheService.IsRedisAvailable() {
		_ = s.permissionCacheService.SetUserMenus(userID, menus)
	}

	return menus, nil
}

// getParentResources 递归获取所有父节点资源
func (s *UserService) getParentResources(parentIDs map[uint]bool) ([]model.Resource, error) {
	if len(parentIDs) == 0 {
		return []model.Resource{}, nil
	}

	// 转换 map 为切片
	ids := make([]uint, 0, len(parentIDs))
	for id := range parentIDs {
		ids = append(ids, id)
	}

	// 查询父节点
	var parents []model.Resource
	err := s.db.Where("id IN ? AND type = 1 AND status = 1", ids).Find(&parents).Error
	if err != nil {
		return nil, err
	}

	// 收集这些父节点的父节点ID
	nextParentIDs := make(map[uint]bool)
	for _, parent := range parents {
		if parent.ParentID > 0 {
			nextParentIDs[parent.ParentID] = true
		}
	}

	// 递归查询更上层的父节点
	if len(nextParentIDs) > 0 {
		grandParents, err := s.getParentResources(nextParentIDs)
		if err != nil {
			return nil, err
		}
		parents = append(parents, grandParents...)
	}

	return parents, nil
}

// GetUserPermissionIDs 已废弃：不再支持用户直接权限
// 用户权限现在完全通过角色来管理
func (s *UserService) GetUserPermissionIDs(userID uint) ([]uint, error) {
	// 返回空列表，保持接口兼容性
	return []uint{}, nil
}

// AssignUserPermissions 已废弃：不再支持用户直接权限分配
// 用户权限现在完全通过角色来管理
func (s *UserService) AssignUserPermissions(userID uint, permissionIDs []uint) error {
	// 不执行任何操作，保持接口兼容性
	return nil
}

// buildMenuTree 构建菜单树
func buildMenuTree(resources []model.Resource, parentID uint) []*dto.MenuData {
	var tree []*dto.MenuData

	for _, resource := range resources {
		if resource.ParentID == parentID {
			menu := &dto.MenuData{
				ID:        resource.ID,
				ParentID:  resource.ParentID,
				Type:      resource.Type,
				Name:      resource.Name,
				Code:      resource.Code,
				Path:      resource.Path,
				Component: resource.Component,
				Icon:      resource.Icon,
				Sort:      resource.Sort,
				IsHidden:  resource.IsHidden,
			}

			// 递归查找子菜单
			children := buildMenuTree(resources, resource.ID)
			if len(children) > 0 {
				menu.Children = children
			}

			tree = append(tree, menu)
		}
	}

	return tree
}
